---
interface Breakpoint {
  emoji: string
  name: string
  width: string
}

interface Props {
  breakpoints: Breakpoint[]
  src: string
}

const { breakpoints, src } = Astro.props
---

<preview-breakpoints data-src={src} class="hidden flex-1 justify-end gap-2 md:flex">
  {
    breakpoints.map(({ emoji, name, width }) => (
      <button
        data-breakpoint={width}
        aria-pressed={width === '100%' ? 'true' : 'false'}
        type="button"
        class="inline-flex items-center gap-2 rounded-lg border border-stone-300 bg-white px-4 py-2 font-medium shadow-sm focus:ring-2 focus:ring-pink-500 focus:outline-0"
      >
        <span aria-hidden="true">{emoji}</span>
        <span>{name}</span>
      </button>
    ))
  }
</preview-breakpoints>

<script>
  class PreviewBreakpoints extends HTMLElement {
    private contentSrc: string | null = null
    private isProcessing = false

    private activeButton: HTMLButtonElement | null = null

    private clickHandler: ((clickEvent: Event) => void) | null = null

    connectedCallback() {
      this.contentSrc = this.dataset.src || null

      if (!this.contentSrc) {
        return
      }

      const buttonEls = [...this.querySelectorAll('button[data-breakpoint]')] as HTMLButtonElement[]

      if (buttonEls.length === 0) {
        return
      }

      this.activeButton =
        buttonEls.find((buttonEl) => buttonEl.getAttribute('aria-pressed') === 'true') ||
        buttonEls.at(-1)!

      this.clickHandler = (clickEvent) => this.handleButtonClick(clickEvent)

      this.addEventListener('click', this.clickHandler)
    }

    private handleButtonClick(clickEvent: Event) {
      if (this.isProcessing) {
        return
      }

      const targetEl = clickEvent.target as HTMLElement
      const buttonEl = targetEl.closest('button[data-breakpoint]') as HTMLButtonElement | null

      if (!buttonEl) {
        return
      }

      this.isProcessing = true

      const width = buttonEl.getAttribute('data-breakpoint')

      if (this.activeButton && this.activeButton !== buttonEl) {
        this.activeButton.setAttribute('aria-pressed', 'false')
      }

      buttonEl.setAttribute('aria-pressed', 'true')

      this.activeButton = buttonEl

      document.dispatchEvent(
        new CustomEvent(`breakpoint:change:${this.contentSrc}`, {
          bubbles: true,
          detail: { width },
        })
      )

      this.isProcessing = false
    }

    disconnectedCallback() {
      if (this.clickHandler) {
        this.removeEventListener('click', this.clickHandler)

        this.clickHandler = null
      }

      this.activeButton = null
    }
  }

  customElements.define('preview-breakpoints', PreviewBreakpoints)
</script>
